package org.cybzacg.encryption;

import org.cybzacg.encryption.config.EncryptionConfig;
import org.cybzacg.encryption.context.EncryptionContext;
import org.cybzacg.encryption.context.impl.DefaultEncryptionContext;
import org.cybzacg.encryption.core.Encryptor;
import org.cybzacg.encryption.enums.EncryptionAlgorithm;
import org.cybzacg.encryption.enums.EncryptionStatus;
import org.cybzacg.encryption.enums.SecurityStrategyEnum;
import org.cybzacg.encryption.exception.EncryptionException;
import org.cybzacg.encryption.listener.EncryptionListener;
import org.cybzacg.encryption.model.EncryptionResult;
import org.cybzacg.encryption.model.ValidationResult;
import org.cybzacg.encryption.strategy.SecurityStrategy;

import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;

import lombok.extern.slf4j.Slf4j;

/**
 * 加密引擎核心类
 * 采用单例模式，提供统一的加密服务入口
 *
 * @author encryption team
 * @version 1.0
 */
@Slf4j
public class EncryptionEngine {

    private static volatile EncryptionEngine instance;
    private static final Object INSTANCE_LOCK = new Object();

    // 线程池配置
    private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors();
    private static final int MAX_POOL_SIZE = CORE_POOL_SIZE * 2;
    private static final int QUEUE_SIZE = 1000;
    private static final long KEEP_ALIVE_TIME = 60L;

    private final Map<EncryptionAlgorithm, Encryptor> encryptors;
    private final Map<SecurityStrategyEnum, SecurityStrategy> strategies;
    private final List<EncryptionListener> listeners;
    private final ReentrantReadWriteLock lock;
    private final ExecutorService executorService;
    private final AtomicReference<EncryptionConfig> defaultConfig;

    private EncryptionEngine() {
        this.encryptors = new ConcurrentHashMap<>();
        this.strategies = new ConcurrentHashMap<>();
        this.listeners = new CopyOnWriteArrayList<>();
        this.lock = new ReentrantReadWriteLock();

        // 使用有界线程池，防止无限增长
        this.executorService = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(QUEUE_SIZE),
                new EncryptionThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略：由调用线程执行
        );

        this.defaultConfig = new AtomicReference<>(EncryptionConfig.createDefault());
    }

    /**
     * 获取单例实例
     *
     * @return 加密引擎实例
     */
    public static EncryptionEngine getInstance() {
        if (instance == null) {
            synchronized (INSTANCE_LOCK) {
                if (instance == null) {
                    instance = new EncryptionEngine();
                }
            }
        }
        return instance;
    }

    /**
     * 加密数据
     *
     * @param data    待加密数据
     * @param context 加密上下文
     * @return 加密结果
     */
    public EncryptionResult encrypt(byte[] data, EncryptionContext context) {
        return executeWithMonitoring("encrypt", () -> {
            validateContext(context);

            // 通知监听器
            notifyListeners(listener -> listener.onEncryptionStart(context));

            try {
                // 获取安全策略
                SecurityStrategy strategy = getStrategy(context.getSecurityStrategy());

                // 执行加密前验证
                ValidationResult validationResult = strategy.validateBeforeEncryption(data, context);
                if (!validationResult.isValid()) {
                    EncryptionResult failureResult = EncryptionResult.failure(
                            EncryptionStatus.INVALID_DATA_FORMAT,
                            validationResult.getMessage(),
                            context);
                    notifyListeners(listener -> listener.onEncryptionFailure(
                            new EncryptionException(validationResult.getMessage()), context));
                    return failureResult;
                }

                // 获取加密器
                Encryptor encryptor = getEncryptor(context.getAlgorithm());

                // 执行加密
                EncryptionResult result = encryptor.encrypt(data, context);

                // 处理结果
                result = strategy.processEncryptionResult(result, context);

                // 通知监听器
                if (result.isSuccess()) {
                    EncryptionResult finalResult1 = result;
                    notifyListeners(listener -> listener.onEncryptionSuccess(finalResult1, context));
                } else {
                    EncryptionResult finalResult = result;
                    notifyListeners(listener -> listener.onEncryptionFailure(
                            new EncryptionException(finalResult.getErrorMessage()), context));
                }

                return result;

            } catch (Exception e) {
                EncryptionException ex = e instanceof EncryptionException ? (EncryptionException) e
                        : new EncryptionException(e.getMessage(), e);

                notifyListeners(listener -> listener.onEncryptionFailure(ex, context));
                throw ex;
            }
        });
    }

    /**
     * 解密数据
     *
     * @param encryptedData 加密数据
     * @param context       解密上下文
     * @return 解密结果
     */
    public EncryptionResult decrypt(byte[] encryptedData, EncryptionContext context) {
        return executeWithMonitoring("decrypt", () -> {
            validateContext(context);

            // 通知监听器
            notifyListeners(listener -> listener.onDecryptionStart(context));

            try {
                // 获取安全策略
                SecurityStrategy strategy = getStrategy(context.getSecurityStrategy());

                // 执行解密前验证
                ValidationResult validationResult = strategy.validateBeforeDecryption(encryptedData, context);
                if (!validationResult.isValid()) {
                    EncryptionResult failureResult = EncryptionResult.failure(
                            EncryptionStatus.INVALID_DATA_FORMAT,
                            validationResult.getMessage(),
                            context);
                    notifyListeners(listener -> listener.onDecryptionFailure(
                            new EncryptionException(validationResult.getMessage()), context));
                    return failureResult;
                }

                // 获取加密器
                Encryptor encryptor = getEncryptor(context.getAlgorithm());

                // 执行解密
                EncryptionResult result = encryptor.decrypt(encryptedData, context);

                // 处理结果
                result = strategy.processDecryptionResult(result, context);

                // 通知监听器
                if (result.isSuccess()) {
                    EncryptionResult finalResult1 = result;
                    notifyListeners(listener -> listener.onDecryptionSuccess(finalResult1, context));
                } else {
                    EncryptionResult finalResult = result;
                    notifyListeners(listener -> listener.onDecryptionFailure(
                            new EncryptionException(finalResult.getErrorMessage()), context));
                }

                return result;

            } catch (Exception e) {
                EncryptionException ex = e instanceof EncryptionException ? (EncryptionException) e
                        : new EncryptionException(e.getMessage(), e);

                notifyListeners(listener -> listener.onDecryptionFailure(ex, context));
                throw ex;
            }
        });
    }

    /**
     * 验证上下文
     *
     * @param context 验证上下文
     * @return 验证结果
     */
    public ValidationResult validate(EncryptionContext context) {
        return executeWithMonitoring("validate", () -> {
            // 通知监听器
            notifyListeners(listener -> listener.onValidationStart(context));

            try {
                // 基本验证
                if (context == null) {
                    ValidationResult failureResult = ValidationResult.failure(
                            "Context cannot be null", "Context is null", context);
                    notifyListeners(listener -> listener.onValidationFailure(
                            new IllegalArgumentException("Context is null"), context));
                    return failureResult;
                }

                if (!context.isValid()) {
                    ValidationResult failureResult = ValidationResult.failure(
                            "Context is invalid", "Context validation failed", context);
                    notifyListeners(listener -> listener.onValidationFailure(
                            new IllegalArgumentException("Context validation failed"), context));
                    return failureResult;
                }

                // 获取加密器验证
                Encryptor encryptor = getEncryptor(context.getAlgorithm());
                ValidationResult result = encryptor.validate(context);

                // 通知监听器
                if (result.isValid()) {
                    notifyListeners(listener -> listener.onValidationSuccess(context));
                } else {
                    notifyListeners(listener -> listener.onValidationFailure(
                            new IllegalArgumentException(result.getMessage()), context));
                }

                return result;

            } catch (Exception e) {
                notifyListeners(listener -> listener.onValidationFailure(e, context));
                return ValidationResult.failure("Validation error", e.getMessage(), context);
            }
        });
    }

    /**
     * 异步加密
     *
     * @param data    待加密数据
     * @param context 加密上下文
     * @return 异步加密结果
     */
    public CompletableFuture<EncryptionResult> encryptAsync(byte[] data, EncryptionContext context) {
        return CompletableFuture.supplyAsync(() -> encrypt(data, context), executorService);
    }

    /**
     * 异步解密
     *
     * @param encryptedData 加密数据
     * @param context       解密上下文
     * @return 异步解密结果
     */
    public CompletableFuture<EncryptionResult> decryptAsync(byte[] encryptedData, EncryptionContext context) {
        return CompletableFuture.supplyAsync(() -> decrypt(encryptedData, context), executorService);
    }

    /**
     * 注册加密器
     *
     * @param encryptor 加密器
     */
    public void registerEncryptor(Encryptor encryptor) {
        if (encryptor == null) {
            throw new IllegalArgumentException("Encryptor cannot be null");
        }

        lock.writeLock().lock();
        try {
            encryptors.put(encryptor.getAlgorithm(), encryptor);
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 注册安全策略
     *
     * @param strategy 安全策略
     */
    public void registerStrategy(SecurityStrategy strategy) {
        if (strategy == null) {
            throw new IllegalArgumentException("Strategy cannot be null");
        }

        lock.writeLock().lock();
        try {
            strategies.put(strategy.getStrategyType(), strategy);
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 添加监听器
     *
     * @param listener 监听器
     */
    public void addListener(EncryptionListener listener) {
        if (listener != null) {
            listeners.add(listener);
        }
    }

    /**
     * 移除监听器
     *
     * @param listener 监听器
     */
    public void removeListener(EncryptionListener listener) {
        listeners.remove(listener);
    }

    /**
     * 获取默认配置
     *
     * @return 默认配置
     */
    public EncryptionConfig getDefaultConfig() {
        return defaultConfig.get();
    }

    /**
     * 设置默认配置
     *
     * @param config 默认配置
     */
    public void setDefaultConfig(EncryptionConfig config) {
        if (config != null) {
            defaultConfig.set(config);
        }
    }

    /**
     * 创建默认上下文
     *
     * @return 默认上下文
     */
    public EncryptionContext createDefaultContext() {
        return DefaultEncryptionContext.fromConfig(getDefaultConfig());
    }

    /**
     * 关闭引擎
     */
    public void shutdown() {
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(30, TimeUnit.SECONDS)) {
                log.warn("线程池未能在30秒内完成所有任务，强制关闭");
                List<Runnable> pending = executorService.shutdownNow();
                log.warn("未完成任务数: {}", pending.size());

                // 等待任务响应中断
                if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
                    log.error("线程池强制关闭后仍有任务未终止");
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("线程池关闭被中断", e);
            executorService.shutdownNow();
        }

        listeners.clear();
        lock.writeLock().lock();
        try {
            encryptors.clear();
            strategies.clear();
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 获取加密器
     */
    private Encryptor getEncryptor(EncryptionAlgorithm algorithm) {
        lock.readLock().lock();
        try {
            Encryptor encryptor = encryptors.get(algorithm);
            if (encryptor == null) {
                throw EncryptionException.algorithmNotSupported(
                        "Algorithm not supported: " + algorithm, null);
            }
            return encryptor;
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取安全策略
     */
    private SecurityStrategy getStrategy(SecurityStrategyEnum strategyType) {
        lock.readLock().lock();
        try {
            SecurityStrategy strategy = strategies.get(strategyType);
            if (strategy == null) {
                throw EncryptionException.configurationError(
                        "Strategy not found: " + strategyType, null);
            }
            return strategy;
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 验证上下文
     */
    private void validateContext(EncryptionContext context) {
        if (context == null) {
            throw new IllegalArgumentException("Context cannot be null");
        }
        if (!context.isValid()) {
            throw new IllegalArgumentException("Context is invalid");
        }
    }

    /**
     * 通知监听器
     */
    private void notifyListeners(java.util.function.Consumer<EncryptionListener> action) {
        for (EncryptionListener listener : listeners) {
            try {
                action.accept(listener);
            } catch (Exception e) {
                // 监听器异常不应该影响主要流程
                log.warn("监听器执行失败: {}", e.getMessage(), e);
            }
        }
    }

    /**
     * 执行带监控的操作
     */
    private <T> T executeWithMonitoring(String operation, Supplier<T> supplier) {
        long startTime = System.currentTimeMillis();
        try {
            T result = supplier.get();
            long duration = System.currentTimeMillis() - startTime;

            // 性能警告检查
            if (duration > 5000) { // 5秒
                notifyListeners(listener -> listener.onPerformanceWarning(duration, null));
            }

            return result;
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            notifyListeners(listener -> listener.onPerformanceWarning(duration, null));
            throw e;
        }
    }

    /**
     * 自定义线程工厂
     */
    private static class EncryptionThreadFactory implements ThreadFactory {
        private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
        private final AtomicInteger counter = new AtomicInteger(0);

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = defaultFactory.newThread(r);
            thread.setName("encryption-thread-" + counter.incrementAndGet());
            thread.setDaemon(true);
            return thread;
        }
    }
}
